/**
 * Copyright (C) 2009 Marcel Urbanek
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package de.urbiworx.sugar;

import java.beans.FeatureDescriptor;
import java.util.Iterator;
import java.util.Map;
import java.util.logging.Logger;

import javax.el.ELContext;
import javax.el.ELResolver;
import javax.faces.context.FacesContext;

import com.google.inject.Key;
import com.google.inject.name.Names;

public class SugaredJSFGuiceELResolver extends ELResolver {    
   
	Logger logger=Logger.getLogger("de.urbiworx.sugar");
	
    @Override
    public Object getValue(ELContext context, Object base, Object property) {

        //Handle only root inquiries, we wont handle property resolving
        if (base!=null)
        {
            return null;
        }        
        if (!(property instanceof String))
        {
        	return null;
        }
        //Get the Configurationmap
        Map <String,SugarConfigurationEntry> configuration=SugarConfigurationHolder.getInstance().getConfiguration();
        Map <String,SugarConfigurationEntry> configurationByView=SugarConfigurationHolder.getInstance().getConfigurationByView();
        //Is this Entry in the loaded Sugar Configuration?
        SugarConfigurationEntry entry;
        if (property.equals("This"))
        {
        	entry=configurationByView.get(FacesContext.getCurrentInstance().getViewRoot().getViewId());
        }
        else
        {
        	entry=configuration.get(property);      
        }
          
        if (entry!=null)
        {
        	
        	Key key;
			try {
				key = Key.get(getClass().getClassLoader().loadClass(entry.getType()), Names.named(entry.getName()));
			} catch (ClassNotFoundException e) {
				//Should not happen, was already checked
				logger.severe("Unexpected error: Class not found:"+entry.getType());
				return null;
			}
			//Ask guice for an object with the given name
        	Object object=SugarConfigurationHolder.getInstance().getInjector().getInstance(key);
        	if (object!=null)
        	{
        		//Only if you set reolved to true, the returned value will be used
        		context.setPropertyResolved(true);
        	}        	
        	return object;
        }
		return null;
		
    }
    /*
     * We dont handle any of this inquiries:
     */
    
    @Override
    public Class<?> getType(ELContext context, Object base, Object property) {
        return null;
    }

    @Override
    public void setValue(ELContext context, Object base, Object property, Object value) {
        //Handle only root inquiries, we wont handle property resolving
        if (base!=null)
        {
            return;
        }        
    	Map<String, SugarConfigurationEntry> configuration=SugarConfigurationHolder.getInstance().getConfiguration();
    	 SugarConfigurationEntry entry=configuration.get(property);
    	if (entry!=null)
    	{
    		Key key=null;
    		try {
				key = Key.get(getClass().getClassLoader().loadClass(entry.getType()), Names.named((String) property));
			} catch (ClassNotFoundException e) {
				//Should not happen, was already checked
				logger.severe("Unexpected error: Class not found:"+entry.getType());
				return;
			}
			if (entry.getScope()==SugarScopeHelper.NONE_SCOPE)
			{
				context.setPropertyResolved(true);
				return;
			}
			
			Map<Key,Object> map=null;
			SugarScopeHelper.setObjectForSugarEntry(value,entry);
			context.setPropertyResolved(true);
    	}
    }


	
	
    @Override
    public boolean isReadOnly(ELContext context, Object base, Object property) {
        return false;
    }

    @Override
    public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext context, Object base) {
        return null;
    }

    @Override
    public Class<?> getCommonPropertyType(ELContext context, Object base) {
        return null;
    }



}
